package com.bf.electroplating.service.compoent;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * HJ212协议数据包解析器
 */
@Slf4j
@Component
public class HJ212PacketParser {
    
    /**
     * 数据包起始符
     */
    private static final String START_FLAG = "##";
    
    /**
     * 数据包结束符
     */
    private static final String END_FLAG = "\r\n";
    
    /**
     * CRC16 校验函数（翻译自 HJ212-2017 标准中的 C 代码）
     *
     * @param msg 输入的字节数组（字符串请使用 .getBytes() 转换）
     * @return CRC16 校验值（int 类型，低字节在前，高字节在后）
     */
    public static int CRC16_Checkout(byte[] msg) {
        int crc_reg = 0xFFFF;
        int check;

        for (int i = 0; i < msg.length; i++) {
            crc_reg = (crc_reg >> 8) ^ (msg[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                check = crc_reg & 0x0001;
                crc_reg >>= 1;
                if (check == 0x0001) {
                    crc_reg ^= 0xA001;
                }
            }
        }
        return crc_reg & 0xFFFF; // 保证返回值为16位
    }

    /**
     * 将 CRC 校验值格式化为 4 位大写十六进制字符串（高位在前，低位在后）
     *
     * @param crc CRC 整型数值
     * @return 格式化字符串（如 BE01）
     */
    public static String formatCRC(int crc) {
        int low = crc & 0x00FF;
        int high = (crc >> 8) & 0x00FF;
        return String.format("%02X%02X", high, low);
    }

    // 示例
    public static void main(String[] args) {
        String input = "QN=20250724162235968;ST=91;CN=9011;PW=123456;MN=72519391;Flag=4;CP=&&QnRtn=9&&";
        byte[] dataBytes = input.getBytes(); // 使用默认 UTF-8 编码；根据 HJ212 一般是 GBK，如需兼容，请使用：input.getBytes("GBK")

        int crcValue = CRC16_Checkout(dataBytes);
        String crcStr = formatCRC(crcValue);
        

        System.out.println("CRC校验值: " + crcStr); // 输出如 "8A6E"
    }
    /**
     * 计算CRC校验码
     * 
     * @param data 需要计算CRC的数据
     * @return CRC校验码（十六进制字符串）
     */
    private String calculateCRC(String data) {
        byte[] dataBytes = data.getBytes();
        int crcValue = CRC16_Checkout(dataBytes);
        String crcStr = formatCRC(crcValue);
        return crcStr;
        // log.info("计算CRC: {}", data);
        // int crc = 0;
        // byte[] bytes = data.getBytes(StandardCharsets.US_ASCII); // 用ASCII编码
        // for (byte b : bytes) {
        //     crc ^= (b & 0xFF);
        //     for (int i = 0; i < 8; i++) {
        //         if ((crc & 0x01) != 0) {
        //             crc = (crc >> 1) ^ 0xA001;
        //         } else {
        //             crc = crc >> 1;
        //         }
        //     }
        // }
        // // 低字节在前，高字节在后
        // return String.format("%02X%02X", crc & 0xFF, (crc >> 8) & 0xFF);
    }
    
    /**
     * 构建完整的HJ212响应包
     * 
     * @param content 响应内容（不包含起始符、长度和CRC）
     * @return 完整的响应包
     */
    private String buildCompleteResponse(String content) {
        // 计算内容长度（ASCII码长度）
        int length = content.getBytes(StandardCharsets.UTF_8).length;
        String lengthStr = String.format("%04d", length);
        
        // 构建完整包（不包含CRC）
        String packetWithoutCRC = START_FLAG + lengthStr + content;
        log.info("START_FLAG: {}", START_FLAG);
        log.info("lengthStr: {}", lengthStr);
        log.info("content: {}", content);
        log.info("packetWithoutCRC: {}", packetWithoutCRC);
        // 计算CRC
        String crc = calculateCRC(content);
        
        // 构建完整响应包
        return packetWithoutCRC + crc + END_FLAG;
    }
    
    /**
     * 解析HJ212数据包
     * 
     * @param data 原始数据
     * @return 解析后的数据包对象
     */
    public HJ212Packet parsePacket(byte[] data) {
        try {
            String message = new String(data, StandardCharsets.UTF_8);
            log.info("收到HJ212数据包: {}", message);
            
            // 检查数据包格式
            if (!message.startsWith(START_FLAG) || !message.endsWith(END_FLAG)) {
                log.warn("数据包格式错误: {}", message);
                return null;
            }
            
            // 移除起始符和结束符
            String content = message.substring(2, message.length() - 2);
            
            // 解析数据包内容
            String[] parts = content.split(";");
            if (parts.length < 2) {
                log.warn("数据包内容格式错误: {}", content);
                return null;
            }
            
            HJ212Packet packet = new HJ212Packet();
            packet.setRawData(data);
            packet.setMessage(message);
            
            // 解析CP参数
            String cp = parts[0];
            packet.setCp(cp);
            
            // 解析数据段
            String dataSegment = parts[1];
            packet.setDataSegment(dataSegment);
            
            // 解析数据区
            if (parts.length > 2) {
                String dataArea = parts[2];
                packet.setDataArea(dataArea);
            }
            
            log.info("解析HJ212数据包成功: CP={}, 数据段={}", cp, dataSegment);
            return packet;
            
        } catch (Exception e) {
            log.error("解析HJ212数据包失败", e);
            return null;
        }
    }
    
    /**
     * 构建确认响应包
     * 
     * @param originalPacket 原始数据包
     * @return 确认响应包
     */
    public byte[] buildAckResponse(HJ212Packet originalPacket) {
        try {
            // 解析原始包中的MN
            String mn = "00000000000000000000";
            String message = originalPacket != null ? originalPacket.getMessage() : null;
            if (message != null) {
                String[] fields = message.split(";");
                for (String field : fields) {
                    if (field.startsWith("MN=")) {
                        mn = field.substring(3);
                        break;
                    }
                }
            }

            // 生成当前时间的QN
            String qn = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());

            // 按指定顺序拼接响应内容
            String content = "QN=" + qn + ";ST=91;CN=9011;PW=123456;MN=" + mn + ";Flag=4;CP=&&QnRtn=1&&";
            
            // 构建完整响应包
            String ackMessage = buildCompleteResponse(content);

            log.info("构建确认响应: {}", ackMessage);
            return ackMessage.getBytes(StandardCharsets.UTF_8);

        } catch (Exception e) {
            log.error("构建确认响应失败", e);
            return null;
        }
    }
    
    /**
     * 构建错误响应包
     * 
     * @param errorCode 错误代码
     * @param errorMsg 错误信息
     * @return 错误响应包
     */
    public byte[] buildErrorResponse(String errorCode, String errorMsg) {
        try {
            // 构建响应内容
            String content = "ST=91;CN=9011;PW=123456;MN=00000000000000000000;Flag=5;CP=&&" + errorMsg + "&&";
            
            // 构建完整响应包
            String errorMessage = buildCompleteResponse(content);
            
            log.info("构建错误响应: {}", errorMessage);
            return errorMessage.getBytes(StandardCharsets.UTF_8);
            
        } catch (Exception e) {
            log.error("构建错误响应失败", e);
            return null;
        }
    }
    
    /**
     * HJ212数据包内部类
     */
    public static class HJ212Packet {
        private byte[] rawData;
        private String message;
        private String cp;
        private String dataSegment;
        private String dataArea;
        
        // Getters and Setters
        public byte[] getRawData() { return rawData; }
        public void setRawData(byte[] rawData) { this.rawData = rawData; }
        
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        
        public String getCp() { return cp; }
        public void setCp(String cp) { this.cp = cp; }
        
        public String getDataSegment() { return dataSegment; }
        public void setDataSegment(String dataSegment) { this.dataSegment = dataSegment; }
        
        public String getDataArea() { return dataArea; }
        public void setDataArea(String dataArea) { this.dataArea = dataArea; }
    }
} 